package it.unibo.refolding.pico.testing;

import it.unibo.refolding.common.CommonThings;
import it.unibo.refolding.common.Images;
import it.unibo.refolding.pico.PicoDataAnalyser;
import it.unibo.refolding.pico.PicoShapes;
import it.unibo.refolding.pico.PlainPicoData;
import it.unibo.refolding.pico.RedundantPicoCurveInfo;
import it.unibo.refolding.pico.Wlc;

import java.awt.Color;
import java.awt.Shape;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;

public class PicoTestUtils {

  private static final Logger logger = Logger.getLogger(PicoTestUtils.class.getSimpleName());

  public static final Path tmpDir = Paths.get(System.getProperty("java.io.tmpdir"));

  public static void drawShapesAndAnalysis(
    List<Shape> ztShapes, List<Shape> dtShapes, double svgDefScale, String prefix, PlainPicoData... a) {
    Path ztSvgPath = tmpDir.resolve(prefix + "_zt.svg");
    logger.log(Level.INFO, "ztSvgFilename: {0}", ztSvgPath);
    Images.saveSvg(ztShapes, ztSvgPath);
    // String dtSvgFilename = System.getProperty("java.io.tmpdir") + "/" +
    // prefix + "_dt.svg";
    // Images.saveSvg(dtShapes, dtSvgFilename);
    // CommonThings.openQuietly(dtSvgFilename);
    Map<Color, List<Shape>> analysisShapes = Maps.newHashMap();
    for (PlainPicoData plainPicoData : a) {
      RedundantPicoCurveInfo analysis = PicoDataAnalyser.analyse(
        plainPicoData, false, PicoDataAnalyser.defaultMinimumPeakForceN,
        PicoDataAnalyser.defaultMinimumPeakContourLengthM,
        PicoDataAnalyser.defaultMinContourLengthDeltaM,
        PicoDataAnalyser.defaultMinPeakForceRelativeToEmpiricalBaselineN,
        PicoDataAnalyser.defaultMedianAbsoluteDeviationLowerBoundN,
        PicoDataAnalyser.defaultLeftMostlyHigherWindowSizeM,
        PicoDataAnalyser.defaultLeftMostlyHigherFraction,
        PicoDataAnalyser.defaultLeftMostlyHigherN,
        PicoDataAnalyser.defaultRightMuchHigherThanAllN,
        PicoDataAnalyser.defaultRightMuchHigherN, PicoDataAnalyser.defaultAtMostOnePeakWindowM,
        Double.NaN, DEFAULT_KBT_OVER_P);
      analysisShapes = CommonThings.unionMapsOfLists(analysisShapes, PicoShapes.draw(analysis, svgDefScale));
    }
    Path dzSvgPath = tmpDir.resolve(prefix + "_dz.svg");
    logger.log(Level.INFO, "dzSvgFilename: {0}", dzSvgPath);
    Images.saveSvg(analysisShapes, dzSvgPath);
  }

  public static void checkActualZRange(
    PlainPicoData plainPicoData, double expectedZRangeM, double allowedRelativeErrorApproach,
    double allowedRelativeErrorRetraction) {
    checkActualZRange(
      plainPicoData.actualZApproachRangeMetres(), expectedZRangeM,
      allowedRelativeErrorRetraction, "approachRatio");
    checkActualZRange(
      plainPicoData.actualZRetractionRangeMetres(), expectedZRangeM,
      allowedRelativeErrorRetraction, "retractionRatio");
  }

  public static void checkActualZRange(
    double actualZRangeM, double expectedZRangeM, double allowedRelativeErrorRetraction, String s) {
    double retractionRatio = actualZRangeM / expectedZRangeM;
    Preconditions.checkState(-(1 + allowedRelativeErrorRetraction) < retractionRatio, s + "="
      + retractionRatio);
    Preconditions.checkState(retractionRatio < -(1 - allowedRelativeErrorRetraction), s + "="
      + retractionRatio);
  }

  public static final double GB1_LINKER_PER_MODULE_NM = 4e-9;

  private static final double DEFAULT_T = 301.15;

  private static final double DEFAULT_P = 0.35e-9;

  public static final double DEFAULT_KBT_OVER_P = Wlc.KB * DEFAULT_T / DEFAULT_P;

  public static final long SEED = computeSeed();

  private static long computeSeed() {
    String s = System.getProperty("test.compactHilbertCurve.seed");
    return s == null ? Calendar.getInstance().get(Calendar.DAY_OF_MONTH) : Long.parseLong(s);
  }
}
